home *** CD-ROM | disk | FTP | other *** search
-
- // Routines to make calls to the real-mode CDROM driver from protected-mode Windows,
- // Using GlobalDOSAlloc and DPMI's int86x service.
-
- // These are allocated in real-mode DOS memory:
-
- DWORD cmdbuf=0, // Buffer for commands, device driver request headers, etc...
- databuf=0, // Buffer for actual data
- buf[MAXNBUF], // Buffer for reading audio data
- prev_end=0; // Buffer for synchronization
-
- WORD cmdbufseg,cmdbufsel,
- databufseg,databufsel, // The same as above, but split into SEG/SEL pairs
- bufseg[MAXNBUF],bufsel[MAXNBUF],
- prev_endseg, prev_endsel;
-
- BYTE *pcmdbuf=0, // Pointers the program can use to access above memory areas
- *pdatabuf=0,
- *pprev_end=0,
- *pbuf[MAXNBUF];
-
- // Set things up to interact with the CDROM driver. Returns 0:Failure, 1:Success
- int startinterfacing(void)
- {
- int i;
-
- memset(buf,0,sizeof(buf)); // zap buffer pointers
-
- cmdbuf=GlobalDosAlloc(32); // 32 bytes for command buffer (BTW, is at most 26 bytes)
- cmdbufseg=HIWORD(cmdbuf);
- cmdbufsel=LOWORD(cmdbuf);
- pcmdbuf=MK_FP(cmdbufsel,0);
-
- if (!cmdbuf) goto Allocerror;
-
- databuf=GlobalDosAlloc(4096); // general purpose data buffer
- databufseg=HIWORD(databuf);
- databufsel=LOWORD(databuf);
- pdatabuf=MK_FP(databufsel,0);
-
- if (!databuf) goto Allocerror;
-
- prev_end=GlobalDosAlloc((long)FRAME_SIZE * NBLOCK);
- prev_endseg=HIWORD(prev_end);
- prev_endsel=LOWORD(prev_end);
- pprev_end=MK_FP(prev_endsel,0);
- if (!prev_end) goto Allocerror;
-
- // Try to allocate as much data buffers if possible, up to MAXNBUF
-
- nbuf=0;
- for (i=0;i<MAXNBUF;i++) {
- buf[nbuf]=GlobalDosAlloc((long)FRAME_SIZE*NBLOCK);
- bufseg[nbuf]=HIWORD(buf[nbuf]);
- bufsel[nbuf]=LOWORD(buf[nbuf]);
- pbuf[nbuf]=MK_FP(bufsel[nbuf],0);
- if (!buf[nbuf]) {
- if (nbuf<2) goto Allocerror;
- break;
- }
- nbuf++;
- }
-
- return 1; // success
-
- Allocerror:
-
- for (i=0;i<nbuf;i++) if (buf[i]) GlobalDosFree(bufsel[i]);
- if (cmdbuf) GlobalDosFree(cmdbufsel);
- if (databuf) GlobalDosFree(databufsel);
- if (prev_end) GlobalDosFree(prev_endsel);
- return 0; // failure
- }
-
-
- // Free the real-mode buffers
- int stopinterfacing(void)
- {
- int i;
- for (i=0;i<nbuf;i++) GlobalDosFree(bufsel[i]);
- GlobalDosFree(cmdbufsel);
- GlobalDosFree(databufsel);
- GlobalDosFree(prev_endsel);
- return 1;
- }
-
- // Used for DPMI call
- struct realregs {
- DWORD edi,esi,ebp,resvd,ebx,edx,ecx,eax;
- WORD flags,es,ds,fs,gs,ip,cs,sp,ss;
- };
-
- int dpmint86(int intnr,struct realregs *in,struct realregs *out)
- {
- union REGS inregs, outregs;
- struct SREGS sregs;
- struct realregs *r;
-
- memset(&inregs,0,sizeof(union REGS)); // Just to be sure there is no junk...
- memset(&outregs,0,sizeof(union REGS));
- memset(&sregs,0,sizeof(struct SREGS));
-
- inregs.x.ax=0x0300; // Simulate Real Mode Interrupt
- inregs.x.bx=intnr; // interrupt #
- inregs.x.di=FP_OFF(in); // address of struct regs
- sregs.es=FP_SEG(in); // ,,
- int86x(0x31,&inregs,&outregs,&sregs); // Call real mode INT via DPMI
- if (outregs.x.cflag) {
- mb("DPMI interface returned error");
- return 1; // DPMI gave error? Exit.
- }
- r=MK_FP(sregs.es, outregs.x.di); // Where to find the output
- if(r->flags & 1) {
- mb("INT2F returned error");
- return 1; // Interrupt in error? Test for carry, exit if 1
- }
- memcpy(out,r,sizeof(struct realregs)); // Get result registers back
- return 0;
- }
-
- // Is MSCDEX installed? (No need for DPMI using this call)
- int CheckMscdex(void)
- {
- union REGS reg;
- reg.x.ax=0x1500; // MSCDEX - Get number of CDROM drives
- reg.x.bx=0;
- int86(0x2f, ®, ®);
- if (!reg.x.bx) return 0; // Nr. of CDROM drives in bx
- CDROM=reg.x.cx; // CX=first CDROM drive (A==0, B==1, etc)
- return 1;
- }
-
- // Call CDROM device driver; command-buffer (at pcmdbuf) must be filled by caller
- void CallDriver(void)
- {
- struct realregs r; // Prepare registers
- memset(&r,0,sizeof(r));
- r.eax=0x1510; // Function: CDROM device driver request
- r.es=cmdbufseg; r.ebx=0; // Address of request structure
- r.ecx=CDROM; // Drive number of CDROM
- dpmint86(0x2f,&r,&r);
- }
-
- // Get CDROM disk information
- int GetDiskInfo(void)
- {
- struct IOCTLI *pcmd=(struct IOCTLI *)pcmdbuf;
- struct DiskInfo *pdi=(struct DiskInfo *)pdatabuf;
-
- pcmd->req.len=26;
- pcmd->req.unit=0;
- pcmd->req.command=3;
- pcmd->descriptor=0;
- pcmd->address=MK_FP(databufseg,0);
- pcmd->len=7;
- pcmd->secnum=0;
- pcmd->ptr=0;
- pdi ->control=10;
-
- CallDriver();
-
- lowest =pdi->lowest;
- highest=pdi->highest;
- total_time=pdi->total;
- return pcmd->req.status;
- }
-
-
- // Read one or more raw audio sectors
- int ReadLong(DWORD loc, WORD secnum,WORD bufseg)
- {
- struct ReadL *pcmd=(struct ReadL *)pcmdbuf;
- pcmd->req.len=sizeof(struct ReadL);
- pcmd->req.unit=0;
- pcmd->req.command=128;
- pcmd->mode=0;
- pcmd->address=MK_FP(bufseg,0);
- pcmd->secnum=secnum;
- pcmd->loc=loc;
- pcmd->readmode=RAW_MODE;
- pcmd->skip[0]=pcmd->skip[1]=0;
- CallDriver();
- return pcmd->req.status;
- }
-
-
- // Convert sector number to printable MM:SS:FF string, for durations.
- char *Sector2MSF(DWORD sector)
- {
- static char s[20];
- long min,sec,frames;
- frames=sector%75;
- sec=sector/75;
- min=sec/60; sec=sec%60;
- sprintf(s,"%02ldm %02lds %02ldf",min,sec,frames);
- return s;
- }
-
- // Convert Sierra sector number to redbook
- DWORD Sierra2Red(DWORD sierra)
- {
- DWORD min,sec,frame,loc;
- sierra+=150; /// ????????????
- frame=sierra%75;
- sec=sierra/75;
- min=sec/60; sec=sec%60;
-
- loc=(BYTE)min;
- loc<<=8; loc|=(BYTE)sec;
- loc<<=8; loc|=(BYTE)frame;
- return loc;
- }
-
-
- // Convert redbood time location to Sierra sector
- DWORD Red2Sierra(DWORD loc)
- {
- BYTE min,sec,frame;
- min=(loc>>16)&0xff;
- sec=(loc>>8)&0xff;
- frame=loc&0xff;
- return (DWORD)min*75*60+(DWORD)sec*75+(DWORD)frame-150;
- }
-
-
- // Convert redbook time location to printable string
- char *Red2MSF(DWORD loc)
- {
- static char s[20];
- BYTE min,sec,frame;
- min=(loc>>16)&0xff;
- sec=(loc>>8)&0xff;
- frame=loc&0xff;
- sprintf(s,"%02um %02us %02uf",min,sec,frame);
- return s;
- }
-
-
- // Convert redbook time location to minute, second, frame, and Sierra sector
- void Red2MSFC(DWORD loc,WORD *min,WORD *sec,WORD *frame,DWORD *sector)
- {
- *frame=loc&0xff;
- loc>>=8; *sec=loc&0xff;
- loc>>=8; *min=loc&0xff;
- *sector=((DWORD)*min)*75*60+((DWORD)*sec)*75+((DWORD)*frame)-150;
- }
-
-
- // Convert minute, second, frame to redbook timecode and Sierra sector
- void MSF2Red(WORD min,WORD sec,WORD frame,DWORD *red,DWORD *sector)
- {
- DWORD loc=0;
- *sector=(DWORD)min*75*60+(DWORD)sec*75+(DWORD)frame-150;
- loc|=min; loc<<=8;
- loc|=sec; loc<<=8;
- loc|=frame;
- *red=loc;
- }
-
-
- // Ask the CDROM device driver information about a track.
- // Given the track number, find out at which sector it starts
- int GetTrackInfo(int track,DWORD *loc)
- {
- struct IOCTLI *pcmd=(struct IOCTLI *)pcmdbuf;
- struct TrackInfo *pbuf=(struct TrackInfo *)pdatabuf;
- pcmd->req.len=26;
- pcmd->req.unit=0;
- pcmd->req.command=3;
- pcmd->descriptor=0;
- pcmd->address=MK_FP(databufseg,0);
- pcmd->len=7;
- pcmd->secnum=0;
- pcmd->ptr=0;
- pbuf->control=11;
- pbuf->track=track;
- CallDriver();
- *loc=pbuf->loc;
- return pcmd->req.status;
- }
-
-
- // Stop playing of current audio piece
- int StopAudio(void)
- {
- struct ReqHdr *pcmd=(struct ReqHdr *)pcmdbuf;
- pcmd->len=13;
- pcmd->unit=0;
- pcmd->command=133;
- CallDriver();
- return pcmd->status;
- }
-
-
- // Play an piece of audio
- int PlayAudio(DWORD loc, DWORD num)
- {
- struct PlayReq *pcmd=(struct PlayReq *)pcmdbuf;
- pcmd->req.len=22;
- pcmd->req.unit=0;
- pcmd->req.command=132;
- pcmd->mode=1;
- pcmd->loc=loc;
- pcmd->secnum=num;
- CallDriver();
- return pcmd->req.status;
- }
-